/*
 ******************************************************************************
 *  Java Signal Framework for routing java objects. 
 *  Copyright (C) 2008  Manuel Stahl (thymythos@web.de)
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ****************************************************************************** 
 */
package org.tru42.signal.processors.parser;

import org.tru42.signal.lang.SObject;
import org.tru42.signal.lang.annotation.Signal;
import org.tru42.signal.lang.annotation.Sink;

public class NMEA extends SObject {

	final static public byte SYNC_START = '$';
	final static public byte PACKET_END = '\n';
	
	private enum State {
		WAIT_FOR_START,
		READ_PACKET
	};
	
	private State state = State.WAIT_FOR_START;
	private StringBuffer packet;

	@Sink
	public void input(long timestamp, byte value) {
		if(state.equals(State.WAIT_FOR_START)) {
			if(value == SYNC_START) {
				packet = new StringBuffer(String.valueOf((char)value));
				state = State.READ_PACKET;
			}
		} else if(state.equals(State.READ_PACKET)) {
			packet.append(String.valueOf((char)value));
			if(value == PACKET_END) {
				parsePacket(packet.toString());							
				state = State.WAIT_FOR_START;
			}
		}				
	}
	
	@Signal
	public void output(long timestamp, NMEAPacket packet) {
	}
	
	public void parsePacket(String packet) {
		if(packet.startsWith(GGA.IDENTIFIER))
			output(System.currentTimeMillis(), new GGA(packet));
	}
	
	public interface NMEAPacket {
		
	};
	
	public class GGA implements NMEAPacket {
		final static public String IDENTIFIER = "$GPGGA,";
		
		public String time;
		public double latitude;
		public char ns;
		public double longitude;
		public char ew;
		public int fix;
		public int numSat;
		public double hdop;
		public double altitude;
		public double altref;
		public double diffAge;
		public int diffStation;
		
		public GGA(String packet) {
			String[] pack = packet.split("\\*");
			if(pack.length != 2) return;
			pack[0] = pack[0] + " ";
			String[] token = pack[0].split(",");
			if(token.length != 15) return;
			
			time = token[1];
			try{latitude = Double.parseDouble(token[2]); } catch(NumberFormatException e) {}
			if(token[3].length() > 0) ns = token[3].charAt(0);
			try{longitude = Double.parseDouble(token[4]);} catch(NumberFormatException e) {}
			if(token[5].length() > 0 ) ew = token[5].charAt(0);
			try{fix = Integer.parseInt(token[6]);} catch(NumberFormatException e) {}
			try{numSat = Integer.parseInt(token[7]);} catch(NumberFormatException e) {}
			try{hdop = Double.parseDouble(token[8]);} catch(NumberFormatException e) {}
			try{altitude = Double.parseDouble(token[9]);} catch(NumberFormatException e) {}
			try{altref = Double.parseDouble(token[11]);} catch(NumberFormatException e) {}
			try{diffAge = Double.parseDouble(token[13]);} catch(NumberFormatException e) {}
			try{diffStation = Integer.parseInt(token[14]);} catch(NumberFormatException e) {}
			//TODO: calc checksum
		}

		@Override
		public String toString() {
			return "GGA: time="+time+" lat="+latitude+" lon="+longitude;
		}
	}
	
}
